package com.ljw.punishment.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.ljw.punishment.baserule.CommonRule;
import com.ljw.punishment.entry.ShopSceneInfoDAO;
import com.ljw.punishment.entry2.ActionDto;
import com.ljw.punishment.entry2.RuleFireResponse;
import com.ljw.punishment.entry2.ShopActionBaseInfoDAO;
import com.ljw.punishment.entry2.ShopRuleViewInfoDAO;
import com.ljw.punishment.rulesengine.RuleEngineBuilder;
import com.ljw.util.SceneTypeEnum;
import lombok.extern.slf4j.Slf4j;
import org.jeasy.rules.api.Facts;
import org.jeasy.rules.api.Rule;
import org.jeasy.rules.api.Rules;
import org.jeasy.rules.api.RulesEngine;
import org.jeasy.rules.support.composite.CompositeRule;
import org.springframework.util.CollectionUtils;

import java.lang.reflect.Field;
import java.util.*;

/**
 * @author lijunwei
 * @date 2025/5/21
 */
@Slf4j
public class RuleOperateServiceImpl {


    public List<RuleFireResponse> doFire(Facts facts, String type) throws Exception {
        SceneTypeEnum sceneTypeByCode = SceneTypeEnum.getSceneTypeByCode(type);
        if (sceneTypeByCode == null) {
            new Exception("不支持的场景类型" + type);
        }
        RuleEngineBuilder ruleEngineBuilder = new RuleEngineBuilder();
        RulesEngine rulesEngine = ruleEngineBuilder.buildRuleEngine(type);
        // 查询指定类型的所有规则code  shop_scene_info
        // List<String> rewardCodes = shopSceneInfoRepository.queryRuleSceneByType(type);
        List<String> rewardCodes = new ArrayList<>();
        rewardCodes.add("check20250519160417339");

        SceneBuilderServiceImpl sceneBuilderService = new SceneBuilderServiceImpl();

        Rules rules = new Rules();
        for (String rewardCode : rewardCodes) {
            // 为每个规则配置构建组合Rule集合：一个模块对应一个AndRelationGroup
            List<CompositeRule> compositeRules = sceneBuilderService.builderRuleByRewardCode(rewardCode, new HashMap<>());
            if (CollectionUtils.isEmpty(compositeRules)) {
                continue;
            }
            for (CompositeRule compositeRule : compositeRules) {
                rules.register(compositeRule);
            }
        }
        rulesEngine.fire(rules, facts);

        Iterator<Rule> iterator = rules.iterator();
        Set<Rule> ruleSet = new HashSet<>();
        while (iterator.hasNext()) {
            ruleSet.add(iterator.next());
        }
        Map<Integer, Facts> resultFromRules = getResultFromRules(ruleSet);

        if (resultFromRules.size() == 0) {
            return new ArrayList<>();
        } else {
            Set<Integer> sceneId = resultFromRules.keySet();
            List<RuleFireResponse> ruleFireResponses = getRuleFireResponses(sceneId);
            log.info("奖惩下发 事实对象 facts:{} , 下发奖惩项 result :{}", JSON.toJSONString(facts), JSON.toJSONString(ruleFireResponses));
            SendMsgTuhuClient sendMsgTuhuClient = new SendMsgTuhuClient();
            sendMsgTuhuClient.notifiedDeveploper("事实对象 fact: " +  JSON.toJSONString(facts) + "命中规则 rules:" + JSONObject.toJSONString(sceneId), "奖惩下发");
            return ruleFireResponses;
        }
    }

    /**
     * CommonRule extends BasicRule
     *                    BasicRule implements Rule
     *
     * public class AndRelationGroup extends UnitRuleGroup
     *                                       UnitRuleGroup extends CompositeRule
     * 									                         CompositeRule extends BasicRule
     * 															                       BasicRule implements Rule
     * @param rulesSet
     * @return
     */
    // 从规则中获取结果
    public Map<Integer, Facts> getResultFromRules(Set<Rule> rulesSet) {
        Map<Integer, Facts> result = new HashMap<>();
        Iterator<Rule> iterator = rulesSet.iterator();
        while (iterator.hasNext()) {
            Rule next = iterator.next();

            if (next instanceof CommonRule) {
                CommonRule commonRule = (CommonRule) next;
                if (commonRule.getResult() != null && commonRule.getResult().size() > 0) {
                    result.putAll(commonRule.getResult());
                }
            }
            // todo 这里明确知道自定义的Rule有哪些类型 可以在子类里提供方法获取Rules属性值
            if (next instanceof CompositeRule) {
                CompositeRule compositeRule = (CompositeRule) next;
                try {
                    Field field = compositeRule.getClass().getSuperclass().getSuperclass().getDeclaredField("rules");
                    field.setAccessible(true);
                    Set<Rule> rules = (Set<Rule>) field.get(compositeRule);

                    if (rules == null || rules.isEmpty()) {
                        continue;
                    }
                    result.putAll(getResultFromRules(rules));
                } catch (Exception e) {
                    log.error("获取处理结果异常", e);
                }
            }
        }
        return result;
    }

    public List<RuleFireResponse> getRuleFireResponses(Set<Integer> sceneIdSet) {
//        List<ShopSceneInfoDAO> shopSceneInfoDoList = shopSceneInfoRepository.querySceneInfoByPKIds(sceneIdSet);
//        System.out.println(JSONObject.toJSONString(shopSceneInfoDoList));
        String shopSceneInfoDoListStr = "[{\"conflictType\":\"throwException\",\"createdBy\":\"shiqi@tuhu.cn\"," +
                "\"effectiveType\":0,\"executeType\":0,\"id\":2164,\"rewardCode\":\"check20250519160417339\"," +
                "\"sceneName\":\"关键规则\",\"sceneType\":\"check\",\"subviewId\":2301,\"viewId\":811}]\n";
        List<ShopSceneInfoDAO> shopSceneInfoDoList = JSON.parseObject(shopSceneInfoDoListStr,
                new TypeReference<List<ShopSceneInfoDAO>>() {
        });

        List<RuleFireResponse> ruleFireResponses = new ArrayList<>();

        for (ShopSceneInfoDAO shopSceneInfoDAO : shopSceneInfoDoList) {
            RuleFireResponse response = new RuleFireResponse();

//            ShopRuleViewInfoDAO shopRuleViewInfoDAO = viewInfoRepository.queryRuleViewByRewardCode(shopSceneInfoDAO
//            .getRewardCode());
//            System.out.println(JSONObject.toJSONString(shopRuleViewInfoDAO));
            String shopRuleViewInfoDAOstr = "{\"createdBy\":\"shiqi@tuhu.cn\",\"createdTime\":1747641857339," +
                    "\"deleteStatus\":0,\"effectiveType\":0,\"enable\":0,\"executeType\":0,\"id\":811," +
                    "\"name\":\"关键规则\",\"rewardCode\":\"check20250519160417339\",\"rewardType\":\"check\"," +
                    "\"updatedBy\":\"shiqi@tuhu.cn\",\"updatedTime\":1747641857339}\n";
            ShopRuleViewInfoDAO shopRuleViewInfoDAO = JSON.parseObject(shopRuleViewInfoDAOstr,
                    ShopRuleViewInfoDAO.class);

            response.setSceneId(String.valueOf(shopSceneInfoDAO.getId()));
            response.setCreateBy(shopSceneInfoDAO.getCreatedBy());
            response.setExecuteType(shopSceneInfoDAO.getExecuteType());
            response.setType(shopSceneInfoDAO.getSceneType());
            response.setRewardCode(shopRuleViewInfoDAO.getRewardCode());
            response.setRewardName(shopRuleViewInfoDAO.getName());

//            List<Integer> actionIds = shopSceneActionRepository.queryActionIdBySceneId(shopSceneInfoDAO.getId());
//            System.out.println(JSONObject.toJSONString(actionIds));
            List<Integer> actionIds = Arrays.asList(126);
//            List<ShopActionBaseInfoDAO> shopActionBaseInfoDAOS = shopActionBaseInfoRepository.queryById(actionIds);
//            System.out.println(JSONObject.toJSONString(shopActionBaseInfoDAOS));
            String shopActionBaseInfoDAOSstr = "[{\"actionCode\":\"money_punish\",\"actionName\":\"罚款\"," +
                    "\"actionType\":\"check\",\"createdBy\":\"zhouyan8@tuhu.cn\",\"createdTime\":1734006100005," +
                    "\"id\":126,\"parameterValue\":\"6\",\"punishObject\":0}]\n";
            List<ShopActionBaseInfoDAO> shopActionBaseInfoDAOS = JSON.parseObject(shopActionBaseInfoDAOSstr,
                    new TypeReference<List<ShopActionBaseInfoDAO>>() {
            });
            List<ActionDto> actionDtoList = new ArrayList<>();
            for (ShopActionBaseInfoDAO shopActionBaseInfoDAO : shopActionBaseInfoDAOS) {
                ActionDto actionDto = new ActionDto();

                actionDto.setId(shopActionBaseInfoDAO.getId());
                actionDto.setActionCode(shopActionBaseInfoDAO.getActionCode());
                actionDto.setActionName(shopActionBaseInfoDAO.getActionName());
                actionDto.setParameterValue(shopActionBaseInfoDAO.getParameterValue());
                actionDto.setParameterExt(shopActionBaseInfoDAO.getParameterExt());
                actionDto.setActionType(shopActionBaseInfoDAO.getActionType());
                actionDtoList.add(actionDto);
            }
            response.setActionDtoList(actionDtoList);

            ruleFireResponses.add(response);
        }
        return ruleFireResponses;
    }

}
